- [Algorithm](#org45219c1)
- [To do ](#org6708989)
- [Survival Stage Generator](#org0613967)
  - [Ideas](#org992122b)
  - [Concept](#org1666248)



<a id="org45219c1"></a>

# Algorithm

The following is a description of the decryption algorithm by A-Man:

> 1-Open the file for reading and store what's inside into a variable (or stream it, whatever you prefer/have available). The content of the file is gibberish (because it's encrypted).
>
> 2-Skip over the first one hundred and twenty three characters and start going through all characters in the file. Since counting in computers starts from 0, this means you will start from the 124rd letter character (index 123).
>
> 3-For every character you go through, convert it to its ASCII code, subtract from it the ASCII code of the Nth character in the key "odBearBecauseHeIsVeryGoodSiuHungIsAGo" (yes, the letters are shifted because there is a caeser cipher step we can skip with using this shifted key).
>
> 4- N is an index in the key which keeps increasing for every character and restarts back to 0 when it reaches the end of the key.
>
> &#x2013; <https://lf-empire.de/forum/showthread.php?pid=198669#pid198669>


<a id="org6708989"></a>

# To do

-   [X] manage to parse the whole `stage.dat`
-   [X] write tests for things in the grammar
-   [ ] create useful accessor functions for parts of the parse tree of `stage.dat`
-   [ ] create procedures for writing data files


<a id="org0613967"></a>

# Survival Stage Generator


<a id="org992122b"></a>

## Ideas


### Phase construction mechanism

-   Could use the previous mechanism of having difficulty ratings and filling up a phase until a difficulty has been reached.


### Other

-   various stage types
-   let users specify functions which determin probability of adding some character
-   let users configure a lot of things via a configuration file
    -   HP levels of characters
    -   boss stage frequency
    -   initial difficulty
    -   character difficulty ratings
    -   probabilities of addind characters
    -   difficulty rating increase per HP
    -   milk frequency
    -   spawn beer yes / no
    -   random seed
    -   boss phases enabled yes/no
    -   all soldiers in boss phases yes/no
-   probabilities for characters to appear in a type of stage
-   default probability for a character to appear in any type of stage
-   perhaps add a factor for increasing probability for a character when phases are higher
-   configuration and random seed together should make for a deterministic stage generation


<a id="org1666248"></a>

## Concept

This section describes the concept of generating a random survival stage.

The idea of having a difficulty rating for each phase in survival stage seems to have worked well in the past. It should probably be kept. The question is then how to put in opponents, so that the intended difficulty is reached and how the difficulty rating develops from early phases to later phases.

There are entities, which are not opponents, which can be added to phases and which might increase or decrease the difficulty of a phase, such as bottles or other items.

In the following these aspects are looked at.


### Putting in entities other than opponents

Most typically in survival stage, milk bottles are spawned at the beginning of each phase. Use of beer bottles could be another advantage. Another idea is to add random items at the beginning of a phase.

The configuration for some ideas for adding non-opponent entities to phases can be put into a configuration file. For example there could be the following configuration attributes:

-   an absolute number of milk bottles, which spawn every phase, regardless of how many players there are or what the game difficulty is (a number of milk bottle entities without ratio attribute)

-   a number of milk bottles per player (milk bottle with ratio attribute)

-   same for beer as for milk

-   an absolute number for random (milk or beer) entities, regardless of how many players there are or what game difficulty is selected

-   a player number dependend and game difficulty dependend number of random items

-   a boolean flag for each kind of item, specifying whether it can be spawned when random items are spawned, including milk and beer bottles

For example the configuration could look something like the following:

```scheme
(define config
  '((items . ((num-milk-per-phase . 1)
              (num-milk-per-phase-ratio . 0.5)

              (num-beer-per-phase . 1)
              (num-beer-per-phase-ratio . 0)

              (num-random-items . 2)
              (num-random-items-ratio . 0.5)

              (random-spawn-baseball . #t)
              (random-spawn-beer . #t)
              (random-spawn-boomerang . #t)
              (random-spawn-hoe . #t)
              (random-spawn-knife . #t)
              (random-spawn-louis-armor-1 . #t)
              (random-spawn-louis-armor-2 . #t)
              (random-spawn-milk . #t)
              (random-spawn-stick . #t)
              (random-spawn-stone . #t)
              (random-spawn-wooden-box . #t)))))
```

Note, that this configuration does not allow for multiple different ratio entities, which might have a different effect than a single ratio entity can have.


### Probabilities

Perhaps probabilities should in some cases not be configured in terms of relative probability between 0 and 1, but instead as weights. Weights given for all possible outcomes and then calculating in the program, which outcome has what chance of happening.

This would make configuration simpler, as one does not need to calculate probabilities so that they add up to 1. For example when specifying what the chances are, that a specific character will be added to a phase, it could be tedious to calculate exactly the chances for each character and might be easier to specify weights. Using weights one could never make a mistake of specifying probabilities, which do not add up to 1.

In some cases a relative probability between 0 and 1 might be preferable as well. For example when there is only the chance for an outcome to happen or not to happen, without many alternative outcomes at that decision point.


### Adding opponents

Currently I have the strategy of adding opponents or other entities 1 by 1. This way opponents can fill up the phase difficulty by adding difficulty rating of their own to the phase until the phase has reached the intended difficulty.

What other approaches of making a phase so and so difficult are there?


#### Probability of adding specific opponents

Not all opponents necessarily need to have the same chance of being added to a phase. For example if there is a boss stage, in which there is a boss with a lot of health points, then adding a Jan will make things much harder, because she will probably heal the boss all the time, unless one can afford to make one player deal with her separately.

Kinds of phases should be configured to have specialize chances for each kind of opponent to be added.


#### Algorithm: Adding opponents 1 by 1

1.  calculate intended phase difficulty rating (`R`)
2.  calculate sum (`D`) of difficulty ratings of entities in the phase
3.  if `D` < `R` then increase difficulty by doing one of the following:
    1.  add an opponent
    2.  increase times of an already added opponent
    3.  increase health points of an already added opponent
4.  go back to step 2

The various actions taken to increase difficulty of a phase should be configurable. Depending on what kind of phase is to be generated, opponents should have different probabilities of being added to the phase. The probability of each of the various actions to increase difficulty themselves should depend on the kind pf phase and be configurable as well.


##### Implementation

For implementation I have the following idea:

The survival stage generation process keeps track of the intended difficulty of a phase and perhaps some other things it needs to keep track of. It chooses the next kind of phase to be generated from a pool of "registered" kinds of phases. A registered kind of phase consists of a (1) symbol to identify it, (2) a configuration for all kinds of configurable properties like probabilities of adding a specific opponent and (3) a procedure, which takes the following arguments:

-   seeded random number generator
-   list of previous stages
-   difficulty of the phase to generate
-   configuration
-   hints from previously applied phase generating procedures

The generating procedure would return the following:

-   The used random number generator, if it is necessary. It would be necessary to return it, if giving the same RNG to the next phase's generator procedure would produce the same random numbers as it did when it was given to the current phase generating procedure. Basically if it loses internal state updates between phase generations.
-   a newly generated phase
-   hints for the next phase generating procedure


###### Phase generation hints

Hints could contain simple counters or advice for the next phase generator. Preferrably the hints should contain information, which is not already contained in the phase the previous phase generator generated, because those can be extracted from the previous phase from the list of already generated phases.

Another aspect is, what hints should look like. Should they be a struct of some kind, or a more flexible thing? Perhaps just an alist of symbols and values to them?


###### List of generated phases

This raises the question of which data structure should be used for the list of generated phases. Perhaps a vector of specified length should be used. Then one could always give the index of the phase, that is to be generated, to the next phase generator and that phase generator can access the vector in O(1) time. Although a list can be fine, if the last phase is simply consed onto it. When storing the complete generated stage, one would only need to reverse the list once (O(n)), which would be acceptable.


### Progression of intended difficulty rating for phases

Phases could have a monotone increase in difficulty, as is done by the old survival stage generator, while each boss phase could have a temporary difficulty boost.

Perhaps other interesting difficulty progressions could be thought of. Perhaps there could be peaks of difficulty and less difficult phases afterwards, but with a general upward trend, like an increasing sine function or similar.

Calculation of target difficulty should be done in a separate function, which takes the following inputs:

-   phase number
-   boss phase frequency
-   ???


### Deciding phase types

There can be many different kinds of phases, such as the ones described in the following sections.

For each of these kinds of phases one can define a probability of being created.

The kinds of phases should be easy to expand to new kinds. There should be some kind of registering logic for registering new kinds of phases, so that other people can easily add their own kind of phase.


#### Hunter and Bandit spam


#### Any specific character or character class spam


#### Heroes with times attribute and optionally supported by others


#### Boss phase


#### Boss phase in which the boss is unknown


#### Multi boss phase


#### Special phase for including Template


#### Fire and ice spam phase


#### Phases in which only milk or beer drops


#### Phases with low health point opponents


#### Phases in which criminals spawn


#### Phases in which opponents come from the left


#### Armored phase


#### Mages phase


#### Completely random


### Phase modificators

Additionally there are modificators of phases, which can either apply to a phase or not:

-   has boss opponent and soldier opponents?
-   has criminals?
-   has milk?
-   has beer?
-   has random item?


### Configuration

This section lists configuration values and describes their usage:

-   general
    -   **random-seed:** random number generator seed
    -   **store-plaintext:** boolean flag, if true then a plaintext version of the survival stage will be stored, instead of only storing a `stage.dat` file
-   items
    -   **num-milk-per-phase:** TODO
    -   **num-milk-per-phase-ratio:** TODO
    -   **num-beer-per-phase:** TODO
    -   **num-beer-per-phase-ratio:** TODO
    -   **num-random-items:**

    -   **num-random-items-ratio:**

    -   **random-spawn-baseball:**

    -   **random-spawn-beer:**

    -   **random-spawn-boomerang:**

    -   **random-spawn-hoe:**

    -   **random-spawn-knife:**

    -   **random-spawn-louis-armor-1:**

    -   **random-spawn-louis-armor-2:**

    -   **random-spawn-milk:**

    -   **random-spawn-stick:**

    -   **random-spawn-stone:**

    -   **random-spawn-wooden-box:**
-   characters
    -   template
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   julian
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   firzen
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   louis-ex
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   justin
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   knight
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   jan
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   monk
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   sorcerer
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   jack
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   mark
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   hunter
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   bandit
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   deep
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   john
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   henry
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   rudolf
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   louis
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   firen
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   freeze
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   dennis
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   woody
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   davis
        -   **added-weight:**

        -   **hp-increase-step:**

        -   **base-difficulty:**

        -   **difficulty-per-hp:**
    -   **boss-characters:** list of character ids or names, which in general can be bosses; for special types of phases other values can be configured
    -   **soldier-characters:** list of character id or names, which in general can be soldiers; for special types of phases other values can be configured
-   phases
    -   common-phase
        -   **hunter-bandit-spam-phase-weight:** weight of adding a Hunter and Bandig spam phase
        -   **[character]-only-phase-weight:** weight of adding a [character] only phase
        -   **heroes-phase-weight:**

        -   **boss-phase-weight:**

        -   **fire-ice-phase-weight:** Firen, Freeze, Firzen?, Sorcerer
        -   **mages-phase:** a phase in which only mages as opponents appear: Firen, Freeze, Sorcerer, John, Jan?, Firzen?
        -   **low-hp-phase-weight:**

        -   **armored-phase-weight:**

        -   **completely-random-phase-weight:**
    -   boss-phases
        -   **standard-boss-phase-weight:**

        -   **unknown-boss-phase-weight:**

        -   **multiple-standard-boss-phase-weight:**

        -   **multiple-unknown-boss-phase-weight:**

        -   **all-soldiers:** boolean flag which determines, whether all of the non-boss opponents will be soldiers
